"""HIS 药品字典路由

包含药品字典相关的 API 接口。
使用 FastAPI-Pagination 库实现现代化分页功能。
"""

from fastapi import APIRouter, Query
from fastapi.responses import JSONResponse
from fastapi_pagination import add_pagination, Params
from fastapi_pagination.ext.sqlmodel import paginate as sqlmodel_paginate
import logging

# 移除 drug_query 依赖，直接操作数据库
from model.his.yp1 import Yp1
from core.db_manager import get_db_session
from sqlmodel import select, func
from util.saas_util import SaasUtil, SaasException
from model.saas.his_drug_info import HisDrugInfo
from config.config_manager import get_hospital_config, get_saas_config, get_batch_config
from service.upload_drug_info_service import drug_upload_service

# 日志
logger = logging.getLogger(__name__)

# 创建路由器
router = APIRouter(prefix="/api/his", tags=["HIS 药品字典"])



@router.get("/drug-dict/count")
async def get_drug_dict_count_api():
    """获取药品字典总记录数"""
    global hospital_name
    try:
        hospital_config = get_hospital_config()
        hospital_name = hospital_config.get("name", "医院")
        
        logger.info(f"开始统计{hospital_name}药品字典总记录数")
        
        # 直接操作数据库获取记录数
        with get_db_session() as session:
            statement = select(func.count(Yp1.idm))
            count = session.execute(statement).scalar()
        
        return {
            "success": True,
            "count": count or 0,
            "hospital": hospital_name
        }
    except Exception as e:
        logger.error(f"统计{hospital_name}药品字典总记录数失败: {str(e)}")
        return JSONResponse(
            status_code=500,
            content={
                "success": False,
                "error": str(e),
                "hospital": hospital_name
            }
        )


@router.get("/drug-dict/page")
async def get_drug_dict_page_api(
    page: int = Query(1, ge=1, description="页码，从1开始"),
    size: int = Query(None, ge=1, description="每页条数，不指定则使用配置文件默认值")
):

    try:
        hospital_config = get_hospital_config()
        hospital_name = hospital_config.get("name", "医院")
        
        # 从配置文件获取默认每页条数
        if size is None:
            size = hospital_config.get("pagination_size", 1000)
        
        logger.info(f"开始获取{hospital_name}药品字典数据 (第 {page} 页，每页 {size} 条)")
        
        # 使用 FastAPI-Pagination 库进行分页查询
        with get_db_session() as session:
            # SQL Server 要求使用 OFFSET 时必须要有 ORDER BY
            statement = select(Yp1).order_by(Yp1.ypmc)
            result = sqlmodel_paginate(session, statement, Params(page=page, size=size))
        
        # 从结果中提取数据和分页信息
        results = result.items
        total = result.total
        total_pages = result.pages
        has_next = page < total_pages
        has_prev = page > 1
        
        logger.info(f"成功获取{hospital_name} {len(results)} 条药品数据")
        
        return {
            "success": True,
            "data": results,
            "pagination": {
                "current_page": page,
                "page_size": size,
                "total_count": total,
                "total_pages": total_pages,
                "has_next": has_next,
                "has_prev": has_prev
            },
            "hospital": hospital_name
        }
        
    except Exception as e:
        logger.error(f"获取{hospital_name}药品字典数据失败: {str(e)}")
        return JSONResponse(
            status_code=500,
            content={
                "success": False,
                "error": str(e),
                "hospital": hospital_config.get("name", "医院")
            }
        )


@router.post("/drug-dict/upload")
async def upload_drug_dict_api():
    """上传医院药品字典到 SaaS 平台 - 使用分批处理机制"""
    hospital_name = drug_upload_service.hospital_name
    
    try:
        logger.info(f"开始上传{hospital_name}药品字典到 SaaS 平台")
        
        # 使用药品上传服务进行分批上传
        upload_result = drug_upload_service.upload_drugs_in_batches()
        
        # 处理上传结果
        if upload_result["total_uploaded"] > 0:
            success_batches = upload_result["success_batches"]
            total_batches = upload_result["total_batches"]
            
            logger.info(f"分批上传完成，总共处理 {total_batches} 批，成功 {success_batches} 批，累计上传 {upload_result['total_uploaded']} 条数据")
            return {
                "success": True,
                "message": f"分批上传完成，成功 {success_batches}/{total_batches} 批",
                "data": {
                    "total_uploaded": upload_result["total_uploaded"],
                    "total_failed": upload_result["total_failed"],
                    "total_batches": total_batches,
                    "success_batches": success_batches,
                    "failed_batches": upload_result["failed_batches"],
                    "upload_results": upload_result["upload_results"]
                },
                "count": upload_result["total_uploaded"],
                "hospital": hospital_name
            }
        else:
            logger.warning("没有数据需要上传或上传失败")
            return {
                "success": False,
                "message": "没有数据需要上传或上传失败",
                "data": {
                    "total_uploaded": 0,
                    "total_failed": upload_result.get("total_failed", 0),
                    "total_batches": upload_result.get("total_batches", 0),
                    "success_batches": 0,
                    "failed_batches": upload_result.get("failed_batches", 0),
                    "upload_results": upload_result.get("upload_results", [])
                },
                "count": 0,
                "hospital": hospital_name
            }

    except SaasException as e:
        logger.error(f"上传{hospital_name}药品字典时发生SaaS HTTP异常: {e}")
        return JSONResponse(
            status_code=e.http_status or 500,
            content={
                "success": False,
                "error": str(e),
                "hospital": hospital_name
            }
        )
    except Exception as e:
        logger.error(f"上传{hospital_name}药品字典失败: {e}", exc_info=True)
        return JSONResponse(
            status_code=500,
            content={
                "success": False,
                "error": str(e),
                "hospital": hospital_name
            }
        )


@router.get("/drug-dict/batch-upload")
async def batch_upload_drug_dict_api():
    """分批上传医院药品字典到 SaaS 平台 - 测试接口
    
    流程：
    1. 分页查询200条数据
    2. 将这200条数据作为一个批次上传到SaaS
    3. 查询下一批200条数据
    4. 继续上传下一批
    5. 循环直到所有数据处理完成
    """
    hospital_config = get_hospital_config()
    hospital_name = hospital_config.get("name", "医院")
    batch_config = get_batch_config()
    batch_size = batch_config.get("upload_batch_size", 200)
    
    try:
        logger.info(f"开始分批上传{hospital_name}药品字典到 SaaS 平台 (每批 {batch_size} 条)")
        
        # 1. 获取SaaS配置
        saas_config = get_saas_config()
        user_account = saas_config.get("user_account")
        user_password = saas_config.get("user_password")
        
        if not user_account or not user_password:
            raise ValueError("SaaS user_account or user_password 未在 config.yaml 中配置")

        # 2. 初始化SaaS工具类并获取token
        saas_util = SaasUtil()
        token = saas_util.get_access_token(user_account, user_password)
        if not token:
            raise Exception("获取SaaS平台token失败")

        # 3. 分批处理逻辑
        total_uploaded = 0
        total_failed = 0
        batch_count = 0
        page = 1
        upload_results = []
        
        logger.info("开始分批上传药品信息到SaaS平台")
        
        while True:
            batch_count += 1
            logger.info(f"开始处理第 {batch_count} 批数据 (第 {page} 页)")
            
            # 3.1 分页查询200条数据
            with get_db_session() as session:
                statement = select(Yp1).order_by(Yp1.ypmc)
                result = sqlmodel_paginate(session, statement, Params(page=page, size=batch_size))
                drugs = result.items
            
            if not drugs:
                logger.info(f"查询完成，没有更多数据")
                break
            
            logger.info(f"查询到第 {page} 页数据，共 {len(drugs)} 条")
            
            # 3.2 数据模型转换
            data_list = []
            for drug in drugs:
                try:
                    # 安全转换 Decimal 为字符串，避免 Pydantic 序列化警告
                    def safe_decimal_to_str(value):
                        """安全地将 Decimal 转换为字符串"""
                        if value is None:
                            return None
                        return str(value)
                    
                    his_drug_info = HisDrugInfo(
                        hisDrugId=drug.idm,
                        hisDrugName=drug.ypmc,
                        hisDrugSpec=drug.ypgg,
                        hisPac=safe_decimal_to_str(drug.ykxs) or "1",
                        hisPacUnit=drug.jhdw,
                        hisDosUnit=drug.zxdw,
                        hisConRatio=safe_decimal_to_str(drug.ykxs),
                        hisDrugManufacturerCode=drug.cjdm,
                        hisDrugManufacturerName=drug.cjmc,
                        hisPurchaseUnit=drug.jhdw,
                        hisPurchasePrice=safe_decimal_to_str(drug.ypfj),
                        hisDoseForm=None,
                        hisApprovalNum=drug.pzwh,
                        hisDrugCountryCode=None,
                    )
                    # 使用 Pydantic 的 model_dump 序列化，同时排除值为None的字段
                    data_list.append(his_drug_info.model_dump(by_alias=True, exclude_none=True))
                except Exception as e:
                    logger.error(f"转换药品数据失败 (ID: {drug.idm}): {e}")
                    continue
            
            if not data_list:
                logger.warning(f"第 {batch_count} 批数据转换后为空，跳过上传")
                page += 1
                continue
            
            # 3.3 上传这200条数据到SaaS
            request_data = {"dataList": data_list}
            result = saas_util.upload_his_drug_info(token, request_data)
            
            if result:
                total_uploaded += len(data_list)
                upload_results.append({
                    "batch": batch_count,
                    "page": page,
                    "count": len(data_list),
                    "success": True
                })
                logger.info(f"第 {batch_count} 批数据上传成功，本批 {len(data_list)} 条，累计 {total_uploaded} 条")
            else:
                total_failed += len(data_list)
                upload_results.append({
                    "batch": batch_count,
                    "page": page,
                    "count": len(data_list),
                    "success": False
                })
                logger.error(f"第 {batch_count} 批数据上传失败")
            
            # 3.4 如果返回的数据少于批次大小，说明已经是最后一批
            if len(drugs) < batch_size:
                logger.info(f"查询完成，已处理所有数据")
                break
            
            # 3.5 准备查询下一批
            page += 1
        
        # 4. 处理上传结果
        success_batches = sum(1 for r in upload_results if r["success"])
        failed_batches = len(upload_results) - success_batches
        
        if total_uploaded > 0:
            logger.info(f"分批上传完成，总共处理 {batch_count} 批，成功 {success_batches} 批，累计上传 {total_uploaded} 条数据")
            return {
                "success": True,
                "message": f"分批上传完成，成功 {success_batches}/{batch_count} 批",
                "data": {
                    "total_uploaded": total_uploaded,
                    "total_failed": total_failed,
                    "total_batches": batch_count,
                    "success_batches": success_batches,
                    "failed_batches": failed_batches,
                    "upload_results": upload_results
                },
                "count": total_uploaded,
                "hospital": hospital_name
            }
        else:
            logger.warning("没有数据需要上传或上传失败")
            return {
                "success": False,
                "message": "没有数据需要上传或上传失败",
                "data": {
                    "total_uploaded": 0,
                    "total_failed": total_failed,
                    "total_batches": batch_count,
                    "success_batches": 0,
                    "failed_batches": failed_batches,
                    "upload_results": upload_results
                },
                "count": 0,
                "hospital": hospital_name
            }

    except SaasException as e:
        logger.error(f"分批上传{hospital_name}药品字典时发生SaaS HTTP异常: {e}")
        return JSONResponse(
            status_code=e.http_status or 500,
            content={
                "success": False,
                "error": str(e),
                "hospital": hospital_name
            }
        )
    except Exception as e:
        logger.error(f"分批上传{hospital_name}药品字典失败: {e}", exc_info=True)
        return JSONResponse(
            status_code=500,
            content={
                "success": False,
                "error": str(e),
                "hospital": hospital_name
            }
        )


# 添加分页支持到路由器
add_pagination(router)

__all__ = ["router"]